#include "route/route.h"

namespace iecas_ns
{
    shared_ptr<CRoute> CRoute::sm_intancePtr = nullptr;

    CRoute::CRoute()
    {
        m_commonPtr = shared_ptr<CCommon>(CCommon::getInstance());
        m_jsonUsrPtr = shared_ptr<CJsonUsr>(CJsonUsr::getInstance());
        m_src_dest_route.clear();
    }

	shared_ptr<CRoute> CRoute::getInstance()
	{
		if(sm_intancePtr == nullptr)
		{
			sm_intancePtr = shared_ptr<CRoute>(new CRoute());
		}
		return sm_intancePtr;
	}

    bool CRoute::init(void)
    {
        if(readRouteFile())
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    void CRoute::start(void)
    {
        thread tempThread(&CRoute::loop, this);
        tempThread.detach();
    }

    void CRoute::loop(void)
    {
        while(true)
        {
            if(!readRouteFile())
            {
                cout << "read route file failed" << endl;
                PLOGD << "read route file failed";
            }
            sleep(5);
        }
    }

    void CRoute::addSingleRoute(Value singleRoute)
    {
        lock_guard<mutex> lockG(CRoute::m_src_dest_Lock);

        string srcDev = singleRoute[SRC_DEV].asString();
        string destDev = singleRoute[DEST_DEV].asString();

        int i;
        for(i = 0; i < m_src_dest_route.size(); i++)
        {
            if((m_src_dest_route[i][SRC_DEV].asString() == srcDev) && (m_src_dest_route[i][DEST_DEV].asString() == destDev))
            {
                cout << "add route failed: " << srcDev << " -> " << destDev << endl;
                PLOGD << "add route failed: " << srcDev << " -> " << destDev;
                break;
            }
        }
        if(i == m_src_dest_route.size())
        {
            Value tmpRoute;
            tmpRoute[SRC_DEV] = srcDev;
            tmpRoute[DEST_DEV] = destDev;
            m_src_dest_route.append(tmpRoute);
            cout << "add route success: " << srcDev << " -> " << destDev << endl;
            PLOGD << "add route success: " << srcDev << " -> " << destDev;
        }
    }

    void CRoute::delSingleRoute(Value singleRoute)
    {
        lock_guard<mutex> lockG(CRoute::m_src_dest_Lock);

        string srcDev = singleRoute[SRC_DEV].asString();
        string destDev = singleRoute[DEST_DEV].asString();
    
        int i;
        for(i = 0; i < m_src_dest_route.size(); i++)
        {
            if((m_src_dest_route[i][SRC_DEV].asString() == srcDev) && (m_src_dest_route[i][DEST_DEV].asString() == destDev))
            {
                Value tmpRoute;
                m_src_dest_route.removeIndex(i, &tmpRoute);
                cout << "del route success: " << srcDev << " -> " << destDev << endl;
                PLOGD << "del route success: " << srcDev << " -> " << destDev;
                break;
            }
        }
        if(i == m_src_dest_route.size())
        {
            cout << "del route failed: " << srcDev << " -> " << destDev << endl;
            PLOGD << "del route failed: " << srcDev << " -> " << destDev;
        }
    }

    bool CRoute::getSingleRoute(string srcDev, vector<string> &destDevAll)
    {
        lock_guard<mutex> lockG(CRoute::m_src_dest_Lock);

        int i;
        for(i = 0; i < m_src_dest_route.size(); i++)
        {
            if(m_src_dest_route[i][SRC_DEV].asString() == srcDev)
            {
                destDevAll.push_back(m_src_dest_route[i][DEST_DEV].asString());
                cout << "get route success: " << srcDev << " -> " << m_src_dest_route[i][DEST_DEV].asString() << endl;
                PLOGD << "get route success: " << srcDev << " -> " << m_src_dest_route[i][DEST_DEV].asString();
            }
        }

        i = destDevAll.size();
        if(i)
        {
            cout << "get route success: " << srcDev << " size: " << i << endl;
            PLOGD << "get route success: " << srcDev << " size: " << i;
            return true;
        }
        else
        {
            cout << "get route failed: " << srcDev << endl;
            PLOGD << "get route failed: " << srcDev;
            return false;
        }
    }

    void CRoute::getAllRoute(Value &allRoute)
    {
        lock_guard<mutex> lockG(CRoute::m_src_dest_Lock);

        allRoute = m_src_dest_route;
    }

    bool CRoute::readRouteFile(void)
    {
        lock_guard<mutex> lockG(CRoute::m_src_dest_Lock);

        if(m_jsonUsrPtr->readFromJsonFile(ROUTES_JSON_FILE_NAME, m_src_dest_route))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    bool CRoute::writeRouteFile(void)
    {
        lock_guard<mutex> lockG(CRoute::m_src_dest_Lock);

        if(m_jsonUsrPtr->writeToJsonFile(ROUTES_JSON_FILE_NAME, m_src_dest_route))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
